package com.gitee.qdbp.jdbc.stream;

import java.util.List;
import java.util.Map;
import com.gitee.qdbp.able.enums.LogicType;
import com.gitee.qdbp.able.jdbc.condition.DbWhere;
import com.gitee.qdbp.able.jdbc.condition.DbWhereForFieldCore;
import com.gitee.qdbp.able.jdbc.condition.DbWhereForOnFieldless;
import com.gitee.qdbp.able.jdbc.condition.DbWhereForStartCore;
import com.gitee.qdbp.able.jdbc.condition.SkipType;
import com.gitee.qdbp.jdbc.api.CrudDao;
import com.gitee.qdbp.jdbc.utils.ParseTools;

/**
 * 递归查询, 设置startCodes之后的流式操作对象
 *
 * @author zhaohuihua
 * @version 20210530
 */
public class RecursiveStartedStream<T> extends RecursiveFilteredStream<T> {

    RecursiveStartedStream(CrudDao<T> dao, String codeField, String parentField, List<String> startCodes) {
        super(dao, codeField, parentField, startCodes, DbWhere.NONE);
    }

    /**
     * 设置数据过滤条件<br>
     * recursiveBy(codeField, parentField) 按什么字段进行递归查询<br>
     * startBy 起始编号<br>
     * filterBy 数据过滤条件, 过滤哪些数据参与递归 (如数据状态,租户编号等条件)<br>
     * searchBy 结果搜索条件 (如用户输入的查询条件) 这些条件如果放在searchWhere中将无法生成完整的树<br>
     * 注意: 查询结果包括startCode节点的自身记录, 如果不需要应在searchWhere条件排除<br>
     * <pre>
    List&lt;SysDept&gt; depts = qdbcBoot.crudStream(SysDept.class)
        .recursiveBy("id", "parentId") // 按id/parentId进行递归查询
        .startBy("D01", "D02") // 起始编号
        .filterBy("tenantCode").equals("T001").end() // 租户编号
        .searchBy("id").notIn("D01", "D02").end() // 查询子节点, 但不要包含起始编号自身
        .listChildren();
        // .listParents();
     * </pre>
     * 
     * @param fieldName 字段名
     * @return 返回后续流式操作对象
     */
    public DbWhereForFieldCore<RecursiveFilteredStream<T>> filterBy(String fieldName) {
        DbWhere where = DbWhere.newEmptiableWhere();
        RecursiveFilteredStream<T> next = new RecursiveFilteredStream<>(dao, codeField, parentField, startCodes, where);
        DbWhereForStartCore<RecursiveFilteredStream<T>> start = new DbWhereForStartCore<>(next, where);
        return new DbWhereForFieldCore<>(start, SkipType.NONE, LogicType.AND, fieldName);
    }

    /**
     * 设置数据过滤条件<br>
     * recursiveBy(codeField, parentField) 按什么字段进行递归查询<br>
     * startBy 起始编号<br>
     * filterBy 数据过滤条件, 过滤哪些数据参与递归 (如数据状态,租户编号等条件)<br>
     * searchBy 结果搜索条件 (如用户输入的查询条件) 这些条件如果放在searchWhere中将无法生成完整的树<br>
     * 注意: 查询结果包括startCode节点的自身记录, 如果不需要应在searchWhere条件排除<br>
     * <pre>
    List&lt;SysDept&gt; depts = qdbcBoot.crudStream(SysDept.class)
        .recursiveBy("id", "parentId") // 按id/parentId进行递归查询
        .startBy("D01", "D02") // 起始编号
        .filterBy().subCondition((w) -> {
                w.on("tenantCode").equals("T001") // 租户编号
                 .or("tenantCode").isNull();
            })
            .end()
        .searchBy("id").notIn("D01", "D02").end() // 查询子节点, 但不要包含起始编号自身
        .listChildren();
        // .listParents();
     * </pre>
     * 
     * @return 返回后续流式操作对象
     */
    public DbWhereForOnFieldless<RecursiveFilteredStream<T>> filterBy() {
        DbWhere where = DbWhere.newEmptiableWhere();
        RecursiveFilteredStream<T> next = new RecursiveFilteredStream<>(dao, codeField, parentField, startCodes, where);
        DbWhereForStartCore<RecursiveFilteredStream<T>> start = new DbWhereForStartCore<>(next, where);
        return new DbWhereForOnFieldless<>(start, SkipType.NONE);
    }

    /**
     * 设置数据过滤条件<br>
     * recursiveBy(codeField, parentField) 按什么字段进行递归查询<br>
     * startBy 起始编号<br>
     * filterBy 数据过滤条件, 过滤哪些数据参与递归 (如数据状态,租户编号等条件)<br>
     * searchBy 结果搜索条件 (如用户输入的查询条件) 这些条件如果放在searchWhere中将无法生成完整的树<br>
     * 注意: 查询结果包括startCode节点的自身记录, 如果不需要应在searchWhere条件排除<br>
     * <pre>
    List&lt;SysDept&gt; depts = qdbcBoot.crudStream(SysDept.class)
        .recursiveBy("id", "parentId") // 按id/parentId进行递归查询
        .startBy("D01", "D02") // 起始编号
        .filterBy(where)
        .searchBy("id").notIn("D01", "D02").end() // 查询子节点, 但不要包含起始编号自身
        .listChildren();
        // .listParents();
     * </pre>
     * 
     * @param filterWhere 数据过滤条件
     * @return 返回后续流式操作对象
     */
    public RecursiveFilteredStream<T> filterBy(DbWhere filterWhere) {
        return new RecursiveFilteredStream<>(dao, codeField, parentField, startCodes, filterWhere);
    }

    /**
     * 设置数据过滤条件 (从实体类构建Where对象)<br>
     * recursiveBy(codeField, parentField) 按什么字段进行递归查询<br>
     * startBy 起始编号<br>
     * filterBy 数据过滤条件, 过滤哪些数据参与递归 (如数据状态,租户编号等条件)<br>
     * searchBy 结果搜索条件 (如用户输入的查询条件) 这些条件如果放在searchWhere中将无法生成完整的树<br>
     * 注意: 查询结果包括startCode节点的自身记录, 如果不需要应在searchWhere条件排除<br>
     * <pre>
    List&lt;SysDept&gt; depts = qdbcBoot.crudStream(SysDept.class)
        .recursiveBy("id", "parentId") // 按id/parentId进行递归查询
        .startBy("D01", "D02") // 起始编号
        .filterBy(deptEntity)
        .searchBy("id").notIn("D01", "D02").end() // 查询子节点, 但不要包含起始编号自身
        .listChildren();
        // .listParents();
     * </pre>
     * 
     * @param entity 实体类
     * @return 返回后续流式操作对象
     * @see ParseTools#parseBeanToDbWhere(Object)
     */
    public RecursiveFilteredStream<T> filterBy(T entity) {
        DbWhere where = dao.plugins().parseTools().parseBeanToDbWhere(entity);
        return filterBy(where);
    }

    /**
     * 设置数据过滤条件 (从Map构建Where对象)<br>
     * recursiveBy(codeField, parentField) 按什么字段进行递归查询<br>
     * startBy 起始编号<br>
     * filterBy 数据过滤条件, 过滤哪些数据参与递归 (如数据状态,租户编号等条件)<br>
     * searchBy 结果搜索条件 (如用户输入的查询条件) 这些条件如果放在searchWhere中将无法生成完整的树<br>
     * 注意: 查询结果包括startCode节点的自身记录, 如果不需要应在searchWhere条件排除<br>
     * <pre>
    List&lt;SysDept&gt; depts = qdbcBoot.crudStream(SysDept.class)
        .recursiveBy("id", "parentId") // 按id/parentId进行递归查询
        .startBy("D01", "D02") // 起始编号
        .filterBy(map)
        .searchBy("id").notIn("D01", "D02").end() // 查询子节点, 但不要包含起始编号自身
        .listChildren();
        // .listParents();
     * </pre>
     * 
     * @param map Map参数
     * @return 返回后续流式操作对象
     * @see ParseTools#parseBeanToDbWhere(Object)
     */
    public RecursiveFilteredStream<T> filterBy(Map<String, Object> map) {
        DbWhere where = dao.plugins().parseTools().parseBeanToDbWhere(map);
        return filterBy(where);
    }

}
